import subprocess
import re
from datetime import datetime, timedelta
from typing import Dict, List, Any
import logging

logger = logging.getLogger(__name__)

class LinuxAuditRules:
    """Linux安全审计规则类"""

    @staticmethod
    def run_cmd_simple(command: str) -> str:
        """简化的命令执行，处理Linux编码问题"""
        try:
            result = subprocess.run(
                command,
                shell=True,
                capture_output=True,
                timeout=30,
                text=True  # 直接返回字符串（Linux默认UTF-8）
            )
            return result.stdout.strip() or result.stderr.strip()
        except Exception as e:
            return f"Error: {str(e)}"

    @staticmethod
    def check_password_policy() -> Dict[str, Any]:
        """1. 检查账户口令策略（强密码+UID=0+空口令+锁定策略）"""
        print("[规则1] 检查账户口令策略...")
        status_details = []
        issues = []

        # 1.1 强密码策略（PAM配置）
        pam_output = LinuxAuditRules.run_cmd_simple(
            "grep -E 'pam_cracklib.so|pam_pwquality.so' /etc/pam.d/system-auth /etc/pam.d/password-auth 2>/dev/null"
        )
        complexity_enabled = "retry=" in pam_output and ("minlen=" in pam_output or "dcredit=" in pam_output)
        min_length = re.search(r"minlen=(\d+)", pam_output)
        min_length = int(min_length.group(1)) if min_length else 0

        if complexity_enabled and min_length >= 12:
            status_details.append(f"✓ 强密码策略: 已启用（最小长度{min_length}位）")
        else:
            issues.append("强密码策略未启用或长度不足12位")
            status_details.append(f"✗ 强密码策略: 未达标（当前长度{min_length}位）")

        # 1.2 非root的UID=0账户
        uid0_users = LinuxAuditRules.run_cmd_simple(
            "awk -F: '$3 == 0 && $1 != \"root\" {print $1}' /etc/passwd"
        )
        if uid0_users:
            issues.append(f"存在非root的UID=0账户: {uid0_users}")
            status_details.append(f"✗ UID=0异常账户: {uid0_users}")
        else:
            status_details.append("✓ UID=0账户: 仅root存在")

        # 1.3 空口令账户
        empty_pass_users = LinuxAuditRules.run_cmd_simple(
            "awk -F: 'length($2) == 0 {print $1}' /etc/shadow"
        )
        if empty_pass_users:
            issues.append(f"存在空口令账户: {empty_pass_users}")
            status_details.append(f"✗ 空口令账户: {empty_pass_users}")
        else:
            status_details.append("✓ 空口令账户: 无")

        # 1.4 账户锁定策略
        lock_policy = LinuxAuditRules.run_cmd_simple(
            "grep -E 'pam_tally2.so|pam_faillock.so' /etc/pam.d/system-auth 2>/dev/null"
        )
        if "deny=" in lock_policy and "unlock_time=" in lock_policy:
            deny = re.search(r"deny=(\d+)", lock_policy).group(1)
            unlock = re.search(r"unlock_time=(\d+)", lock_policy).group(1)
            status_details.append(f"✓ 锁定策略: 连续{deny}次失败锁定{unlock}秒")
        else:
            issues.append("未配置账户锁定策略")
            status_details.append("✗ 锁定策略: 未启用")

        return {
            "rule_name": "账户口令策略检查",
            "status": "通过" if not issues else "未通过",
            "config_status": {
                "complexity_enabled": complexity_enabled,
                "min_password_length": min_length,
                "uid0_users": uid0_users.split() if uid0_users else [],
                "empty_pass_users": empty_pass_users.split() if empty_pass_users else [],
                "lock_policy_enabled": "deny=" in lock_policy
            },
            "status_details": status_details,
            "recommendation": "口令策略符合要求" if not issues else f"需修复: {'; '.join(issues)}"
        }

    @staticmethod
    def check_sudo_su_permissions() -> Dict[str, Any]:
        """2. 检查su/sudo权限管理"""
        print("[规则2] 检查su/sudo权限...")
        status_details = []
        issues = []

        # 2.1 限制su仅允许root
        su_restrict = LinuxAuditRules.run_cmd_simple(
            "grep 'pam_wheel.so use_uid' /etc/pam.d/su 2>/dev/null"
        )
        if su_restrict:
            status_details.append("✓ su权限: 仅允许wheel组使用")
        else:
            issues.append("未限制su命令使用范围")
            status_details.append("✗ su权限: 无限制（任何用户可尝试su）")

        # 2.2 搜索所有sudo权限（用户+组）
        sudo_users = LinuxAuditRules.run_cmd_simple(
            "grep -v '^#' /etc/sudoers | grep -E '^[a-zA-Z0-9%]+.*ALL=\(ALL\)' 2>/dev/null"
        )
        sudo_entries = sudo_users.splitlines() if sudo_users else []
        if len(sudo_entries) > 0:
            status_details.append(f"✓ sudo配置项数量: {len(sudo_entries)}")
            for entry in sudo_entries[:3]:  # 显示前3项
                status_details.append(f"  - {entry}")
            if any("%sudo" in e or "%wheel" in e for e in sudo_entries):
                status_details.append("✓ 已通过组配置sudo权限")
            else:
                issues.append("存在直接配置用户sudo权限的条目")
        else:
            status_details.append("✓ sudo配置: 无额外权限条目")

        return {
            "rule_name": "su/sudo权限检查",
            "status": "通过" if not issues else "未通过",
            "config_status": {
                "su_restricted": bool(su_restrict),
                "sudo_entry_count": len(sudo_entries),
                "sudo_entries": sudo_entries
            },
            "status_details": status_details,
            "recommendation": "权限配置合理" if not issues else f"需修复: {'; '.join(issues)}"
        }

    @staticmethod
    def check_suid_files() -> Dict[str, Any]:
        """3. 检查SUID高危文件（完整输出所有高危项）"""
        print("[规则3] 检查SUID高危文件...")
        status_details = []
        high_risk_suid = []

        # 查找所有SUID文件
        suid_files = LinuxAuditRules.run_cmd_simple(
            "find / -perm -4000 2>/dev/null | grep -E '/bin/|/usr/bin/|/sbin/'"
        )
        suid_list = suid_files.splitlines() if suid_files else []

        # 高危SUID文件列表（精确匹配）
        risky_binaries = [
            "chmod", "chown", "find", "vi", "vim", "nano", "perl", "python",
            "bash", "sh", "cp", "mv", "tar", "gzip", "wget", "curl", "chsh", "passwd"
        ]
        for file in suid_list:
            if any(bin in file.split('/')[-1] for bin in risky_binaries):
                high_risk_suid.append(file)

        status_details.append(f"✓ 系统SUID文件总数: {len(suid_list)}")
        if high_risk_suid:
            status_details.append(f"✗ 高危SUID文件数量: {len(high_risk_suid)}")
            for file in high_risk_suid:  # 输出所有高危文件
                status_details.append(f"  - {file}")
        else:
            status_details.append("✓ 未发现高危SUID文件")

        return {
            "rule_name": "SUID权限检查",
            "status": "正常" if not high_risk_suid else "异常",
            "config_status": {
                "total_suid_files": len(suid_list),
                "high_risk_suid_files": high_risk_suid,
                "risk_count": len(high_risk_suid)
            },
            "status_details": status_details,
            "recommendation": "无高危SUID文件" if not high_risk_suid else "建议执行 `chmod u-s <文件路径>` 移除所有高危文件的SUID权限"
        }

    @staticmethod
    def check_autostart_services() -> Dict[str, Any]:
        """4. 检查自启服务（完整输出所有自启项和风险项）"""
        print("[规则4] 检查自启服务...")
        status_details = []
        autostart_services = []
        risky_services = []

        # 4.1 systemd自启服务（完整输出前10个）
        systemd_enabled = LinuxAuditRules.run_cmd_simple(
            "systemctl list-unit-files | grep enabled | grep -v '^#' | head -50"  # 限制数量避免输出过长
        )
        systemd_list = systemd_enabled.splitlines() if systemd_enabled else []
        autostart_services.extend([line.split()[0] for line in systemd_list])
        status_details.append(f"✓ systemd自启服务总数: {len(systemd_list)}")

        # 完整输出所有自启服务
        for service in systemd_list:
            service_name = service.split()[0]
            status_details.append(f"  - {service}")

        # 4.2 传统自启目录（完整输出所有项）
        rc_local = LinuxAuditRules.run_cmd_simple("cat /etc/rc.local 2>/dev/null | grep -v '^#' | grep -v 'exit 0'")
        rc_local_items = rc_local.splitlines() if rc_local else []
        if rc_local_items:
            status_details.append(f"✗ /etc/rc.local自启项总数: {len(rc_local_items)}")
            for item in rc_local_items:
                status_details.append(f"  - {item}")
        else:
            status_details.append("✓ /etc/rc.local: 无额外自启项")

        # 检测非必要服务（完整输出所有风险项）
        unnecessary_services = ["telnet", "ftp", "vsftpd", "rpcbind", "nfs", "sendmail"]
        risky_services = [s for s in autostart_services if any(us in s for us in unnecessary_services)]
        if risky_services:
            status_details.append(f"✗ 非必要自启服务数量: {len(risky_services)}")
            for service in risky_services:
                status_details.append(f"  - {service}")

        return {
            "rule_name": "自启服务检查",
            "status": "正常" if not risky_services and not rc_local_items else "异常",
            "config_status": {
                "systemd_enabled_count": len(systemd_list),
                "rc_local_items_count": len(rc_local_items),
                "risky_services": risky_services,
                "rc_local_items": rc_local_items
            },
            "status_details": status_details,
            "recommendation": "自启服务配置合理" if not risky_services and not rc_local_items else f"建议禁用: {', '.join(risky_services)} 并清理 /etc/rc.local 自启项"
        }#该文件中的自定义命令可能存在未被监控的风险操作（如启动未授权程序）建议rc_local全部禁用。

    @staticmethod
    def check_high_risk_ports() -> Dict[str, Any]:
        """5. 检查高危端口/服务（完整输出所有高危项）"""
        print("[规则5] 检查高危端口/服务...")
        status_details = []
        risky_ports = []

        # 监听端口（完整输出）
        netstat_output = LinuxAuditRules.run_cmd_simple(
            "netstat -tulnp 2>/dev/null | grep LISTEN"
        )
        listening_ports = netstat_output.splitlines() if netstat_output else []
        status_details.append(f"✓ 监听端口总数: {len(listening_ports)}")
        for port in listening_ports[:10]:  # 输出前10个，若不足则全部输出
            status_details.append(f"  - {port}")

        # 高危端口映射（精确匹配并完整输出）
        high_risk_ports = {
            "21": "FTP", "23": "Telnet", "25": "SMTP", "135": "RPC",
            "139": "NetBIOS", "445": "SMB", "3306": "MySQL", "6379": "Redis",
            "8080": "Web服务", "3389": "远程桌面", "5432": "PostgreSQL", "6379": "Redis"
        }
        for line in listening_ports:
            for port, service in high_risk_ports.items():
                if f":{port}" in line:
                    process = line.split()[-1].split('/')[-1] if '/' in line.split()[-1] else "未知进程"
                    risky_ports.append(f"端口{port} ({service}) - {process}")

        if risky_ports:
            status_details.append(f"✗ 高危端口数量: {len(risky_ports)}")
            for port in risky_ports:  # 输出所有高危端口
                status_details.append(f"  - {port}")
        else:
            status_details.append("✓ 未发现高危端口监听")

        return {
            "rule_name": "高危端口检查",
            "status": "正常" if not risky_ports else "异常",
            "config_status": {
                "total_listening_ports": len(listening_ports),
                "high_risk_ports": risky_ports
            },
            "status_details": status_details,
            "recommendation": "无高危端口暴露" if not risky_ports else "建议关闭或防火墙限制所有高危端口"
        }

    @staticmethod
    def check_cron_jobs() -> Dict[str, Any]:
        """6. 检查定时任务"""
        print("[规则6] 检查定时任务...")
        status_details = []
        suspicious_crons = []

        # 系统级定时任务
        system_crons = LinuxAuditRules.run_cmd_simple("ls -l /etc/cron* 2>/dev/null")
        # 用户级定时任务
        user_crons = LinuxAuditRules.run_cmd_simple(
            "for user in $(cut -f1 -d: /etc/passwd); do crontab -l -u $user 2>/dev/null; done"
        )

        # 高危特征
        risky_patterns = [
            "wget", "curl", "bash -i", "nc ", "netcat", "/dev/tcp/",
            "rm -rf", "mkfifo", "python -c"
        ]

        for line in user_crons.splitlines() + system_crons.splitlines():
            if any(p in line for p in risky_patterns):
                suspicious_crons.append(line.strip())

        status_details.append("✓ 系统级定时任务: 存在/etc/cron*配置")
        status_details.append(f"✓ 用户级定时任务行数: {len(user_crons.splitlines())}")

        if suspicious_crons:
            status_details.append(f"✗ 可疑定时任务数量: {len(suspicious_crons)}")
            for cron in suspicious_crons[:3]:
                status_details.append(f"  - {cron}")
        else:
            status_details.append("✓ 未发现可疑定时任务")

        return {
            "rule_name": "定时任务检查",
            "status": "正常" if not suspicious_crons else "异常",
            "config_status": {
                "has_system_crons": bool(system_crons),
                "user_cron_count": len(user_crons.splitlines()),
                "suspicious_crons": suspicious_crons
            },
            "status_details": status_details,
            "recommendation": "定时任务正常" if not suspicious_crons else "建议清除可疑定时任务"
        }

    @staticmethod
    def check_backdoor_files() -> Dict[str, Any]:
        """7. 检查后门文件/木马"""
        print("[规则7] 检查后门文件...")
        status_details = []
        suspicious_files = []

        # 7.1 SSH后门（未授权密钥）- 完整列出所有文件
        ssh_keys = LinuxAuditRules.run_cmd_simple(
            "find /root/.ssh/ /home/*/.ssh/ -name 'authorized_keys' 2>/dev/null"
        )
        ssh_key_list = ssh_keys.splitlines() if ssh_keys else []
        if ssh_key_list:
            status_details.append(f"✓ SSH密钥文件总数: {len(ssh_key_list)}")
            # 完整列出所有SSH密钥文件
            for key_file in ssh_key_list:
                status_details.append(f"  - {key_file}")
        else:
            status_details.append("✓ 未发现SSH密钥文件")

        # 7.2 /tmp敏感文件 - 完整列出所有可疑可执行文件
        tmp_files = LinuxAuditRules.run_cmd_simple(
            "find /tmp -type f -mtime -7 -perm -o+x 2>/dev/null"  # 近7天可执行文件
        )
        tmp_file_list = tmp_files.splitlines() if tmp_files else []
        if tmp_file_list:
            suspicious_files.extend(tmp_file_list)
            status_details.append(f"✗ /tmp可疑可执行文件总数: {len(tmp_file_list)}个")
            # 完整列出所有/tmp下的可疑文件
            for file in tmp_file_list:
                status_details.append(f"  - {file}")
        else:
            status_details.append("✓ /tmp目录: 未发现近7天的可疑可执行文件")

        # 7.3 其他高危目录 - 完整列出所有隐藏文件
        other_risky = LinuxAuditRules.run_cmd_simple(
            "find /dev/shm/ /usr/local/bin/ -type f -name '.*' 2>/dev/null"  # 隐藏文件
        )
        other_risky_list = other_risky.splitlines() if other_risky else []
        if other_risky_list:
            suspicious_files.extend(other_risky_list)
            status_details.append(f"✗ 高危目录隐藏文件总数: {len(other_risky_list)}个")
            # 完整列出所有高危目录的隐藏文件
            for file in other_risky_list:
                status_details.append(f"  - {file}")
        else:
            status_details.append("✓ 高危目录(/dev/shm/、/usr/local/bin/): 未发现隐藏文件")

        return {
            "rule_name": "后门文件检查",
            "status": "正常" if not suspicious_files else "异常",
            "config_status": {
                "ssh_key_files": ssh_key_list,  # 保存所有SSH密钥文件
                "tmp_suspicious_files": tmp_file_list,  # 保存所有/tmp可疑文件
                "other_risky_files": other_risky_list,  # 保存所有高危目录隐藏文件
                "suspicious_files_count": len(suspicious_files),
                "suspicious_files": suspicious_files  # 完整列出所有可疑文件
            },
            "status_details": status_details,
            "recommendation": "未发现可疑文件" if not suspicious_files else "建议检查并删除所有列出的可疑文件"
        }

    @staticmethod
    def check_hids_status() -> Dict[str, Any]:
        """8. 检查HIDS日志审计与响应检查，增强应用服务日志监控检测"""
        print("[规则8] 检查HIDS状态及应用服务日志监控...")
        status_details = []
        hids_config = "/var/ossec/etc/ossec.conf"  # 通用配置路径（可覆盖Wazuh/Ossec）
        hids_running = False
        hids_type = "未知"  # 记录HIDS类型

        # 第一步：通过进程检测HIDS运行状态
        hids_process_keywords = ["wazuh", "ossec", "falco", "sysdig-agent", "trivy-agent"]
        for keyword in hids_process_keywords:
            process_check = LinuxAuditRules.run_cmd_simple(f"ps aux | grep -v grep | grep -i {keyword}")
            if process_check:
                hids_running = True
                hids_type = keyword.capitalize()
                status_details.append(f"✓ 进程检测: {hids_type} 进程正在运行")
                break
        if not hids_running:
            status_details.append(f"✗ 进程检测: 未发现任何HIDS进程")

        # 第二步：通过systemctl检测服务状态
        hids_services = [
            "wazuh", "wazuh-manager", "wazuh-agent",
            "ossec", "ossec-manager", "ossec-agent",
            "falco", "sysdig-agent", "trivy-agent"
        ]
        service_status = "未检测到服务"
        for service in hids_services:
            service_check = LinuxAuditRules.run_cmd_simple(f"systemctl status {service} 2>/dev/null")
            if "active (running)" in service_check:
                service_status = f"{service} 正在运行"
                break
            elif "inactive (dead)" in service_check:
                service_status = f"{service} 已安装但未启动"
        status_details.append(f"ℹ️ 服务状态: {service_status}")

        # 第三步：检查配置文件与基础日志监控
        config_exists = LinuxAuditRules.run_cmd_simple(f"test -f {hids_config} && echo 1 || echo 0")
        if config_exists == "1":
            status_details.append(f"✓ 配置文件: {hids_config} 存在")

            # 读取配置文件内容用于后续分析
            config_content = LinuxAuditRules.run_cmd_simple(f"cat {hids_config} 2>/dev/null")

            # 提取基础日志路径
            log_paths = re.findall(
                r'(?:<location>|path=)"([^"]+)"',
                config_content
            )
            status_details.append(f"✓ 基础审计日志数量: {len(log_paths)}")
            for path in log_paths[:3]:  # 显示前3个作为示例
                status_details.append(f"  - {path}")
        else:
            status_details.append(f"✗ 配置文件: 未找到 {hids_config}")
            config_content = ""

        # 第四步：增强功能 - 检查关键应用服务日志监控（包含MySQL，redis,nginx,secure,apache,Tomcat）
        critical_services = {
            "MySQL": {
                "log_paths": [
                    "/var/log/mysql/mysql.log", "/var/log/mysql/error.log",
                    "/var/log/mysqld.log", "/var/log/mysql/mysql-error.log"
                ],
                "importance": "高危",
                "description": "数据库操作审计、SQL注入检测"
            },
            "Redis": {
                "log_paths": [
                    "/var/log/redis/redis-server.log", "/var/log/redis.log",
                    "/var/log/redis/redis.log"
                ],
                "importance": "高危",
                "description": "缓存数据库未授权访问检测"
            },
            "Apache": {
                "log_paths": [
                    "/var/log/apache2/access.log", "/var/log/apache2/error.log",
                    "/var/log/httpd/access_log", "/var/log/httpd/error_log"
                ],
                "importance": "中危",
                "description": "Web攻击检测、访问异常监控"
            },
            "Nginx": {
                "log_paths": [
                    "/var/log/nginx/access.log", "/var/log/nginx/error.log"
                ],
                "importance": "中危",
                "description": "Web服务器攻击检测"
            },
            "Tomcat": {
                "log_paths": [
                    "/var/log/tomcat/catalina.out",
                    "/var/log/tomcat9/catalina.out",
                    "/opt/tomcat/logs/catalina.out",
                    "/usr/share/tomcat/logs/catalina.out",
                    "/var/log/tomcat/localhost.log",
                    "/var/log/tomcat9/localhost.log",
                    "/opt/tomcat/logs/localhost.log",
                    "/var/log/tomcat/manager.log",
                    "/var/log/tomcat9/manager.log",
                    "/opt/tomcat/logs/manager.log",
                    "/var/log/tomcat/host-manager.log",
                    "/var/log/tomcat9/host-manager.log"
                ],
                "importance": "高危",
                "description": "Java应用漏洞、Web攻击检测"
            },
            "SSH": {
                "log_paths": [
                    "/var/log/auth.log", "/var/log/secure"
                ],
                "importance": "高危",
                "description": "暴力破解、异常登录检测"
            },
            "系统认证": {
                "log_paths": [
                    "/var/log/auth.log", "/var/log/secure"
                ],
                "importance": "高危",
                "description": "用户登录、权限变更监控"
            }
        }

        monitored_services = []
        unmonitored_services = []
        monitoring_details = []

        if config_exists == "1" and config_content:
            # 分析每个关键服务的日志监控状态
            for service_name, service_info in critical_services.items():
                service_monitored = False
                monitored_paths = []

                for log_path in service_info["log_paths"]:
                    # 检查配置文件是否包含该日志路径（支持多种配置格式）
                    path_patterns = [
                        f'<location>{log_path}</location>',
                        f'path="{log_path}"',
                        f'>{log_path}<',
                        log_path  # 直接路径匹配
                    ]

                    for pattern in path_patterns:
                        if pattern in config_content:
                            service_monitored = True
                            monitored_paths.append(log_path)
                            break

                if service_monitored:
                    monitored_services.append(service_name)
                    monitoring_details.append({
                        "service": service_name,
                        "status": "已监控",
                        "paths": monitored_paths,
                        "importance": service_info["importance"]
                    })
                    status_details.append(f"✅ {service_name}监控: 已配置 ({service_info['description']})")
                    for path in monitored_paths[:2]:  # 显示前2个监控路径
                        status_details.append(f"    📍 监控路径: {path}")
                else:
                    unmonitored_services.append(service_name)
                    status_details.append(f"❌ {service_name}监控: 未配置 ({service_info['description']})")
                    # 为Tomcat提供更详细的建议
                    if service_name == "Tomcat":
                        # 先尝试自动检测Tomcat安装路径
                        tomcat_paths = [
                            "/var/log/tomcat", "/var/log/tomcat9",
                            "/opt/tomcat/logs", "/usr/share/tomcat/logs",
                            "/home/*/tomcat/logs", "/home/*/apache-tomcat*/logs"
                        ]
                        detected_paths = []
                        for path_pattern in tomcat_paths:
                            path_check = LinuxAuditRules.run_cmd_simple(f"ls -d {path_pattern} 2>/dev/null")
                            if path_check and "No such file" not in path_check:
                                detected_paths.extend(path_check.strip().split('\n'))

                        if detected_paths:
                            status_details.append(f"    💡 检测到Tomcat日志路径: {', '.join(detected_paths[:3])}")
                        else:
                            status_details.append(f"    💡 建议监控: {service_info['log_paths'][0]}")
                    else:
                        status_details.append(f"    💡 建议监控: {service_info['log_paths'][0]}")
        else:
            # 如果配置文件不存在，所有服务都标记为未监控
            unmonitored_services = list(critical_services.keys())
            for service_name in unmonitored_services:
                status_details.append(f"❌ {service_name}监控: HIDS未安装")

        # 第五步：检查主动响应配置
        active_response = "未配置"
        if config_exists == "1" and config_content:
            ar_keywords = ["<active-response>", "auto_response", "active_action"]
            ar_check = LinuxAuditRules.run_cmd_simple(
                f"grep -E '{'|'.join(ar_keywords)}' {hids_config} 2>/dev/null"
            )
            active_response = "已配置" if ar_check else "未配置"
        status_details.append(f"🔧 主动响应: {active_response}")

        # 第六步：综合状态判定
        total_services = len(critical_services)
        monitored_count = len(monitored_services)
        monitoring_coverage = monitored_count / total_services if total_services > 0 else 0

        # 风险评估逻辑
        if not hids_running:
            final_status = "HIDS未运行"
            risk_level = "高风险"
        elif monitored_count == 0:
            final_status = "HIDS运行中但未监控关键服务"
            risk_level = "高风险"
        elif monitoring_coverage < 0.3:  # 覆盖率低于30%
            final_status = "关键服务监控严重不足"
            risk_level = "高风险"
        elif monitoring_coverage < 0.6:  # 覆盖率30%-60%
            final_status = "关键服务监控不足"
            risk_level = "中风险"
        else:
            final_status = "监控覆盖良好"
            risk_level = "低风险"

        # 添加监控覆盖率摘要
        status_details.append("\n📊 监控覆盖率摘要:")
        status_details.append(f"   ✅ 已监控服务: {monitored_count}/{total_services}")
        status_details.append(f"   📈 监控覆盖率: {monitoring_coverage:.1%}")
        status_details.append(f"   🚨 风险等级: {risk_level}")

        return {
            "rule_name": "HIDS及应用服务日志监控检查",
            "status": final_status,
            "config_status": {
                "hids_type": hids_type,
                "hids_running": hids_running,
                "config_file_exists": config_exists == "1",
                "service_status": service_status,
                "active_response_enabled": active_response == "已配置",
                "monitored_services": monitored_services,
                "unmonitored_services": unmonitored_services,
                "monitoring_coverage": f"{monitoring_coverage:.1%}",
                "critical_services_total": total_services,
                "risk_assessment": risk_level,
                "monitoring_details": monitoring_details
            },
            "status_details": status_details,
            "recommendation": (
                f"HIDS运行正常，监控了 {monitored_count}/{total_services} 个关键服务" if hids_running and monitored_count > 0 else
                f"建议配置关键服务日志监控，当前仅覆盖 {monitored_count}/{total_services} 个服务" if hids_running else
                "请先安装并启动HIDS系统"
            )
        }

    @staticmethod
    def check_firewall_status() -> Dict[str, Any]:
        """9. 检查防火墙状态（适配iptables的active (exited)状态）"""
        print("[规则9] 检查防火墙状态...")
        status_details = []
        firewall_active = False

        # 1. 检查firewalld（需active (running)）
        firewalld = LinuxAuditRules.run_cmd_simple("systemctl status firewalld 2>/dev/null")
        if "active (running)" in firewalld:
            firewall_active = True
            status_details.append("✓ firewalld: 服务运行中")
        else:
            # 2. 检查iptables（active (exited)视为成功启动，因规则已加载）
            iptables = LinuxAuditRules.run_cmd_simple("systemctl status iptables 2>/dev/null")
            if "active (exited)" in iptables or "active (running)" in iptables:
                # 验证是否有规则（避免空规则场景）
                iptables_rules = LinuxAuditRules.run_cmd_simple("iptables -L -n 2>/dev/null")
                if len(iptables_rules.splitlines()) > 5:
                    firewall_active = True
                    status_details.append("✓ iptables: 服务已启动且规则已加载")
                else:
                    status_details.append("✗ iptables: 服务已启动但无有效规则")
            else:
                status_details.append("✗ 防火墙: 未启用（firewalld和iptables均未启动）")

        return {
            "rule_name": "防火墙状态检查",
            "status": "正常" if firewall_active else "异常",
            "config_status": {
                "firewall_active": firewall_active,
                "firewalld_running": "active (running)" in firewalld,
                "iptables_active": "active (exited)" in iptables or "active (running)" in iptables
            },
            "status_details": status_details,
            "recommendation": "防火墙运行正常" if firewall_active else "建议启用firewalld或启动iptables服务并配置规则"
        }

    import datetime  # 需导入datetime模块

    @staticmethod
    def check_history_commands() -> Dict[str, Any]:
        """10. 检查历史记录高危指令（输出所有检测到的危险命令，不省略）"""
        print("[规则10] 检查历史命令...")
        status_details = []
        risky_commands = []

        # 检查历史记录时间戳配置
        hist_config = LinuxAuditRules.run_cmd_simple("grep HISTTIMEFORMAT /etc/profile 2>/dev/null")
        if hist_config:
            status_details.append("✓ 历史记录: 已配置时间戳")
        else:
            status_details.append("✗ 历史记录: 未配置时间戳（建议开启）")

        # 生成要扫描的历史文件列表
        home_users = LinuxAuditRules.run_cmd_simple("ls /home/ 2>/dev/null").split()
        history_files = ["/root/.bash_history"] + [f"/home/{u}/.bash_history" for u in home_users if u.strip()]

        # 定义高危命令模式
        risky_patterns = [
            "rm -rf /", "mkfs.", "fdisk", "dd if=/dev/", "bash -i >& /dev/tcp/",
            "nc ", "netcat ", "wget http://", "curl http://", "chmod 777 "
        ]

        # 扫描每个历史文件中的高危命令
        for hist_file in history_files:
            # 检查文件是否存在
            if LinuxAuditRules.run_cmd_simple(f"test -f {hist_file} && echo 1 || echo 0") == "1":
                content = LinuxAuditRules.run_cmd_simple(f"cat {hist_file} 2>/dev/null")
                # 遍历所有命令行（不再限制最近100条，完整扫描）
                for line in content.splitlines():
                    if any(p in line for p in risky_patterns):
                        risky_commands.append(f"{hist_file}: {line}")

        # 整理输出结果
        if risky_commands:
            status_details.append(f"✗ 高危命令总数: {len(risky_commands)}")
            # 输出所有高危命令，不做省略
            for cmd in risky_commands:
                status_details.append(f"  - {cmd}")
        else:
            status_details.append("✓ 未发现高危命令")

        return {
            "rule_name": "历史命令审计",
            "status": "正常" if not risky_commands else "异常",
            "config_status": {
                "hist_timestamp_enabled": bool(hist_config),
                "risky_commands": risky_commands  # 完整保留所有命令
            },
            "status_details": status_details,
            "recommendation": "历史命令无异常" if not risky_commands else "建议核查所有高危命令来源"
        }

    @staticmethod
    def check_system_logs() -> Dict[str, Any]:
        """11. 简化版系统基础日志服务检查"""
        print("[规则11] 检查系统基础日志服务状态...")
        status_details = []
        issues = []

        # 1. 检查rsyslog核心服务
        rsyslog = LinuxAuditRules.run_cmd_simple("systemctl status rsyslog 2>/dev/null")
        if "active (running)" in rsyslog:
            status_details.append("✓ rsyslog服务: 运行中")
        else:
            issues.append("rsyslog服务未运行")
            status_details.append("✗ rsyslog服务: 未运行")

        # 2. 检查关键日志文件存在性
        critical_logs = {
            "认证日志": ["/var/log/auth.log", "/var/log/secure"],
            "系统日志": ["/var/log/syslog", "/var/log/messages"],
            "登录记录": ["/var/log/wtmp", "/var/log/btmp", "/var/log/lastlog"]
        }
        for log_type, paths in critical_logs.items():
            found = False
            for path in paths:
                if LinuxAuditRules.run_cmd_simple(f"test -f {path} && echo 1 || echo 0") == "1":
                    status_details.append(f"✓ {log_type}: {path} 存在")
                    found = True
                    break
            if not found:
                issues.append(f"{log_type}日志文件不存在")
                status_details.append(f"✗ {log_type}: 未找到日志文件")

        # 3. 检查失败登录记录
        failed_login = False
        for auth_log in ["/var/log/auth.log", "/var/log/secure"]:
            if LinuxAuditRules.run_cmd_simple(f"test -f {auth_log} && echo 1 || echo 0") == "1":
                count = LinuxAuditRules.run_cmd_simple(
                    f"grep -c 'Failed password' {auth_log} 2>/dev/null"
                )
                if count.isdigit() and int(count) > 0:
                    failed_login = True
                    status_details.append(f"⚠️ 失败登录: 发现{count}次尝试")
                    if int(count) > 10:
                        issues.append("失败登录次数过多")
        if not failed_login:
            status_details.append("✓ 失败登录: 未发现近期异常")

        # 风险与结果汇总
        return {
            "rule_name": "系统基础日志服务检查",
            "status": "正常" if not issues else "异常",
            "status_details": status_details,
            "recommendation": (
                "系统日志服务运行正常" if not issues else
                "建议修复日志服务或异常登录问题"
            )
        }

    @staticmethod
    def check_sshd_security() -> Dict[str, Any]:
        """12. 检测sshd服务安全配置"""
        print("[规则12] 检查sshd服务安全配置...")
        status_details = []
        issues = []
        sshd_config = "/etc/ssh/sshd_config"

        # 1. 检查sshd服务是否运行
        sshd_running = LinuxAuditRules.run_cmd_simple("systemctl is-active sshd 2>/dev/null")
        if sshd_running == "active":
            status_details.append("✓ sshd服务: 运行中")
        else:
            issues.append("sshd服务未运行")
            status_details.append("✗ sshd服务: 未运行")
            # 服务未运行时仍检查配置文件，不直接返回

        # 2. 检查sshd配置文件是否存在
        if LinuxAuditRules.run_cmd_simple(f"test -f {sshd_config} && echo 1 || echo 0") != "1":
            issues.append("sshd配置文件不存在")
            status_details.append(f"✗ 配置文件: {sshd_config} 不存在")
            return {
                "rule_name": "sshd服务安全配置检查",
                "status": "异常",
                "status_details": status_details,
                "recommendation": "修复sshd配置文件或重新安装openssh-server"
            }

        # 3. 核心安全配置检查（读取配置值，无配置则视为风险）
        def get_config(key: str) -> str:
            return LinuxAuditRules.run_cmd_simple(
                f"grep -E '^#?{key}' {sshd_config} | tail -1 | awk '{{print $2}}' 2>/dev/null"
            ).strip()

        # 关键配置项及安全值
        security_configs = {
            "PermitRootLogin": "no",  # 禁止root直接登录
            "PasswordAuthentication": "no",  # 禁用密码登录（推荐密钥）
            "PermitEmptyPasswords": "no",  # 禁止空密码
            "Port": "22以外端口",  # 非默认端口（检测是否为22）
            "MaxAuthTries": "3"  # 最大认证尝试次数≤3
        }

        # 检查每个配置
        for key, safe_val in security_configs.items():
            current_val = get_config(key)
            if not current_val:
                issues.append(f"未配置 {key}（建议设为 {safe_val}）")
                status_details.append(f"✗ {key}: 未配置（推荐 {safe_val}）")
            else:
                if (key == "Port" and current_val == "22") or \
                        (key != "Port" and current_val != safe_val):
                    issues.append(f"{key} 配置不安全（当前: {current_val}，推荐: {safe_val}）")
                    status_details.append(f"✗ {key}: 当前 {current_val}（推荐 {safe_val}）")
                else:
                    status_details.append(f"✓ {key}: 配置安全（{current_val}）")

        # 结果汇总
        return {
            "rule_name": "sshd服务安全配置检查",
            "status": "正常" if not issues else "异常",
            "status_details": status_details,
            "recommendation": (
                "sshd安全配置符合要求" if not issues else
                f"请修复以下配置: {'; '.join(issues)}"
            )
        }

    @staticmethod
    def get_all_rules() -> List[callable]:
        """获取所有审计规则的函数列表"""
        return [
            LinuxAuditRules.check_password_policy,
            LinuxAuditRules.check_sudo_su_permissions,
            LinuxAuditRules.check_suid_files,
            LinuxAuditRules.check_autostart_services,
            LinuxAuditRules.check_high_risk_ports,
            LinuxAuditRules.check_cron_jobs,
            LinuxAuditRules.check_backdoor_files,
            LinuxAuditRules.check_hids_status,
            LinuxAuditRules.check_firewall_status,
            LinuxAuditRules.check_history_commands,
            LinuxAuditRules.check_system_logs,
            LinuxAuditRules.check_sshd_security

        ]